home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-20 | 8.7 KB | 341 lines | [TEXT/PJMM] |
- unit TalkUDPPackets;
-
- { This program was written by Peter N Lewis, Mar 1992 in THINK Pascal 4.0.1 }
-
- interface
-
- uses
- TalkdTypes;
-
- type
- whenType = (WT_Now, WT_Soon, WT_Delayed);
-
- function InitUDPPackets: OSErr;
- { procedure HandleReceive(data:univ longInt; request,response:ctlMsg)}
- procedure FinishUDPPackets;
- function CreateUDPChannel (data: univ longInt; id: longInt; var localport: integer): OSErr;
- procedure SendPacket (data: univ longInt; when: whenType; var request: ctlMsg; remoteIP: longInt; remoteport: integer);
- procedure DestroyUDPChannel (data: univ longInt);
- function ReceivePacket (var data: univ longInt; var request, response: ctlMsg): boolean;
- function FindRequest (id: longInt; var data: univ longInt): boolean;
- procedure SendOnePacket (var request: ctlMsg; remoteIP: longInt; remoteport: integer);
-
- implementation
-
- uses
- UDPStuff, MyLists;
-
- const
- k_resend_delay = 60 * 2; { two seconds }
- k_daemon_delay = 60 * 2; { delay between calling SendPacket and sending to a delayed port }
-
- type
- packetRecord = record
- udpc: UDPConnectionPtr;
- dead: boolean;
- data: longInt;
- id: longInt;
- refreshtime: longInt;
- remoteIP: longInt;
- remoteport: integer;
- cvt: longInt;
- firstsend: boolean;
- request: ctlMsg;
- end;
- packetPtr = ^packetRecord;
-
- var
- udplist: listHead;
-
- function InitUDPPackets: OSErr;
- begin
- InitUDPPackets := noErr;
- CreateList(udplist);
- end;
-
- procedure DestroyChannel (item: listItem);
- var
- prp: packetPtr;
- oe: OSErr;
- begin
- DeleteItem(item, prp);
- oe := UDPRelease(prp^.udpc);
- DisposPtr(ptr(prp));
- end;
-
- procedure FinishUDPPackets;
- var
- oe: OSErr;
- item: listItem;
- begin
- while not IsEmpty(udplist) do begin
- ReturnHead(udplist, item);
- DestroyChannel(item);
- end;
- DestroyList(udplist, false);
- end;
-
- function CreateUDPChannelP (data: univ longInt; id: longInt; var localport: integer; var prp: packetPtr): OSErr;
- var
- udpc: UDPConnectionPtr;
- oe: OSErr;
- begin
- oe := UDPCreateDynamic(udpc, 0, localport);
- if oe = noErr then begin
- prp := packetPtr(Newptr(SizeOf(packetRecord)));
- prp^.udpc := udpc;
- prp^.dead := true;
- prp^.data := data;
- prp^.id := id;
- prp^.cvt := 0;
- AddTail(udplist, prp);
- end;
- CreateUDPChannelP := oe;
- end;
-
- function CreateUDPChannel (data: univ longInt; id: longInt; var localport: integer): OSErr;
- var
- prp: packetPtr;
- begin
- CreateUDPChannel := CreateUDPChannelP(data, id, localport, prp);
- end;
-
- { cvt 0=bsd 4.3, 1=sun/bsd 4.2 }
- procedure NToORequest (cvt: longInt; var request, orequest: ctlMsg; var datalen: integer; var dstport: integer);
- var
- ocr: octlMsg;
- i: integer;
- begin
- case cvt of
- 0: begin
- orequest := request;
- datalen := SizeOf(ctlMsg);
- dstport := talkd_port;
- end;
- 1: begin
- ocr.data[1] := chr(ord(request.typ));
- BlockMove(@request.l_name, @ocr.data[2], oname_size);
- ocr.data[10] := chr(0);
- BlockMove(@request.r_name, @ocr.data[11], oname_size);
- ocr.data[19] := chr(0);
- ocr.data[20] := chr(0);
- ocr.pid := request.pid;
- ocr.id_num := request.id_num;
- ocr.r_tty := request.r_tty;
- ocr.addr := request.addr;
- ocr.ctl_addr := request.ctl_addr;
- datalen := SizeOf(octlMsg);
- BlockMove(@ocr, @orequest, datalen);
- dstport := otalkd_port;
- if request.typ = CT_Delete then
- cvt := cvt;
- end;
- end;
- end;
-
- procedure OToNResponse (cvt: longInt; remoteport: integer; datap: ptr; datalen: integer; var response: ctlMsg);
- var
- ocr: octlResponse;
- ocrs: octlResponseSmall;
- begin
- if cvt = 1 then
- cvt := cvt;
- response.vers := -1;
- if remoteport = otalkd_port then begin
- if cvt = 1 then begin
- if datalen = SizeOf(octlResponse) then begin
- BlockMove(datap, @ocr, datalen);
- if (0 <= ord(ocr.typ)) and (ord(ocr.typ) <= 3) then
- response.vers := talk_version;
- response.typ := ocr.typ;
- response.answer := ocr.answer;
- response.id_num := ocr.id_num;
- response.addr := ocr.addr;
- end
- else if datalen = SizeOf(octlResponseSmall) then begin
- BlockMove(datap, @ocrs, datalen);
- if (0 <= ord(ocrs.typ)) and (ord(ocrs.typ) <= 3) then
- response.vers := talk_version;
- response.typ := ocrs.typ;
- response.answer := ocrs.answer;
- response.id_num := ocrs.id_num;
- response.addr := ocrs.addr;
- end;
- end;
- end
- else begin
- if (datalen = SizeOf(ctlMsg)) or (datalen = SizeOf(ctlResponse)) then
- BlockMove(datap, @response, datalen);
- end;
- end;
-
- function FindRequest (id: longInt; var data: univ longInt): boolean;
- var
- item: listItem;
- prp: packetPtr;
- begin
- FindRequest := false;
- ReturnHead(udplist, item);
- while not IsTail(item) do begin
- Fetch(item, prp);
- if prp^.id = id then begin
- data := prp^.data;
- FindRequest := true;
- leave;
- end;
- MoveToNext(item);
- end;
- end;
-
- function Find (data: longInt; var item: listItem; var prp: packetPtr): boolean;
- begin
- Find := false;
- ReturnHead(udplist, item);
- while not IsTail(item) do begin
- Fetch(item, prp);
- if prp^.data = data then begin
- Find := true;
- leave;
- end;
- MoveToNext(item);
- end;
- end;
-
- procedure DestroyUDPChannel (data: univ longInt);
- var
- item: listItem;
- prp: packetPtr;
- begin
- if Find(data, item, prp) then begin
- DestroyChannel(item);
- end;
- end;
-
- procedure DestroyUDPChannelP (prp: packetPtr);
- var
- item: listItem;
- begin
- if FindItem(udplist, prp, item) then begin
- DestroyChannel(item);
- end;
- end;
-
- procedure SendPacketP (prp: packetPtr; when: whenType; var request: ctlMsg; remoteIP: longInt; remoteport: integer);
- var
- oe: OSErr;
- begin
- prp^.dead := false;
- if when <> WT_Soon then
- prp^.refreshtime := TickCount + k_daemon_delay
- else
- prp^.refreshtime := TickCount - 1;
- prp^.request := request;
- prp^.remoteIP := remoteIp;
- prp^.remoteport := remoteport;
- prp^.firstsend := true;
- prp^.cvt := 0;
- if when = WT_Now then begin
- oe := UDPWrite(prp^.udpc, prp^.remoteIP, prp^.remoteport, @prp^.request, SizeOf(ctlMsg), false);
- end;
- end;
-
- procedure SendPacket (data: univ longInt; when: whenType; var request: ctlMsg; remoteIP: longInt; remoteport: integer);
- var
- item: listItem;
- prp: packetPtr;
- oe: OSErr;
- begin
- if Find(data, item, prp) then begin
- SendPacketP(prp, when, request, remoteIP, remoteport);
- end;
- end;
-
- procedure SendOnePacket (var request: ctlMsg; remoteIP: longInt; remoteport: integer);
- var
- prp: packetPtr;
- begin
- if CreateUDPChannelP(0, 0, request.ctl_addr.port, prp) = noErr then begin
- SendPacketP(prp, WT_Now, request, remoteIP, remoteport);
- end;
- end;
-
- function FindIP (remoteIP: longInt; remoteport: integer; var prp: packetPtr): boolean;
- var
- item: listItem;
- begin
- FindIP := false;
- ReturnHead(udplist, item);
- while not IsTail(item) do begin
- Fetch(item, prp);
- if (prp^.remoteIP = remoteIP) and (prp^.remoteport = remoteport) then begin
- FindIP := true;
- leave;
- end;
- MoveToNext(item);
- end;
- end;
-
- function ReceivePacket (var data: univ longInt; var request, response: ctlMsg): boolean;
- var
- item: listItem;
- prp: packetptr;
- datap: ptr;
- datalen: integer;
- remoteIP: longInt;
- remoteport: integer;
- dstport: integer;
- ocr: ctlMsg;
- oe: OSErr;
- begin
- ReturnHead(udplist, item);
- while not IsTail(item) do begin
- Fetch(item, prp);
- if UDPDatagramsAvailable(prp^.udpc) > 0 then begin
- oe := UDPRead(prp^.udpc, 2, remoteIP, remoteport, datap, datalen);
- if oe <> noErr then
- leave;
- if remoteIP <> $86073203 then
- prp := prp;
- if datalen > 0 then begin
- OToNResponse(prp^.cvt, remoteport, datap, datalen, response);
- oe := UDPReturnBuffer(prp^.udpc, datap);
- if prp^.data = 0 then begin
- DestroyUDPChannelP(prp);
- leave;
- end
- else begin
- if (prp^.request.typ = response.typ) and (prp^.request.vers = response.vers) and (not prp^.dead) then begin
- ReceivePacket := true;
- data := prp^.data;
- prp^.dead := true;
- request := prp^.request;
- Exit(ReceivePacket);
- end;
- end;
- end;
- end;
- MoveToNext(item);
- end;
- ReturnHead(udplist, item);
- while not IsTail(item) do begin
- Fetch(item, prp);
- if (TickCount > prp^.refreshtime) and (not prp^.dead) then begin
- if prp^.firstsend then
- prp^.firstsend := false
- else if prp^.remoteport = talkd_port then
- prp^.cvt := 1;
- oe := UDPWrite(prp^.udpc, prp^.remoteIP, prp^.remoteport, @prp^.request, SizeOf(ctlMsg), false);
- if prp^.cvt = 1 then begin
- NToORequest(prp^.cvt, prp^.request, ocr, datalen, dstport);
- if prp^.request.typ = CT_Delete then
- prp := prp;
- oe := UDPWrite(prp^.udpc, prp^.remoteIP, dstport, @ocr, datalen, false);
- end;
- prp^.refreshtime := TickCount + k_resend_delay;
- end;
- MoveToNext(item);
- end;
- ReceivePacket := false;
- end;
-
- end.